#include "GlIndexBuffer.h"
#include  "../GL/libExt/libExt.h"
namespace gname
{
GlIndexBuffer::GlIndexBuffer(int indexT,int Usage)
{
	locked = false;
	indexBuffer = 0;
	usage = Usage;
	indexCount = 0;
	indexType = indexT;
	if(!isExtensionSupported("GL_ARB_vertex_buffer_object"))
	{
		
	      // throw std::exception::exception( "Cant create VBO Array without extension GL_ARB_vertex_buffer_object");
    }

	switch(indexType)
	{
	case	GL_UNSIGNED_BYTE:
		indexTypeSizeInBytes = 1;
		break;
	case	GL_UNSIGNED_SHORT:
		indexTypeSizeInBytes = 2;
		break;
	case	GL_UNSIGNED_INT:
		indexTypeSizeInBytes = 4;
	}
}
GlIndexBuffer::GlIndexBuffer()
{
	locked = false;
	indexBuffer = 0;
	usage = GL_STATIC_DRAW;
	indexCount = 0;
	indexTypeSizeInBytes = 4;
	if(!isExtensionSupported("GL_ARB_vertex_buffer_object"))
	{
		
	      // throw std::exception::exception( "Cant create VBO Array without extension GL_ARB_vertex_buffer_object");
    }
}
void GlIndexBuffer::Alloc	( int n )
{
	indexCount = n;
	indexBuffer = new unsigned char[indexCount*indexTypeSizeInBytes];
}

void GlIndexBuffer::IboInit()
{
	
	GenBuffer();
	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, iboId);
	glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, Size()*indexTypeSizeInBytes,indexBuffer,usage);


	initArrays = true;
}

unsigned GlIndexBuffer::GetId() const
{
	return iboId;
}
unsigned	GlIndexBuffer::Size  ( void )	const
{
	return	indexCount;
}

void GlIndexBuffer::Resize	( int n )
{
	if(n==indexCount)
	{
		return;
	}

	indexCount = n;
	Lock();
	
	unsigned char* tmpInd;

	try
	{
		tmpInd	= new unsigned char[indexCount*indexTypeSizeInBytes];
	}
	catch(...)
	{
		
		indexCount = 0;
	}

	memcpy ( tmpInd, indexBuffer, indexCount*indexTypeSizeInBytes );

	Clear();
	
	indexBuffer = tmpInd;
	
	IboInit();
	

	
	
	




	Unlock();
	
}
void GlIndexBuffer::Clear	( void )
{
	   DeleteBuffer();
       if(indexBuffer!=0)
        delete [] indexBuffer;
}
void GlIndexBuffer::Erase	(unsigned index )
{
}

int	GlIndexBuffer::GetElementType()       const
{
	return 0;
}
int	GlIndexBuffer::GetIndexType()         const
{
	return indexType;
}
int	GlIndexBuffer::GetIndexSizeInBytes()	const
{
	return indexTypeSizeInBytes;
}

unsigned int*   GlIndexBuffer::GetIndicesui()
{
	
	return (unsigned int*)	indexBuffer;
}
unsigned short*	GlIndexBuffer::GetIndicesus()
{
	
	return (unsigned short*)indexBuffer;
}
unsigned char*  GlIndexBuffer::GetIndicesub()
{
	
	return	indexBuffer;
}

void GlIndexBuffer::SetIndexData(unsigned char *data)
{
	memcpy(indexBuffer,data,Size()*indexTypeSizeInBytes);
}
bool GlIndexBuffer::Empty ()		const
{
	return indexCount == 0;
}



void GlIndexBuffer::GenBuffer()
{
	if(iboId == 0)
	{
		glGenBuffersARB(1, &iboId);
		
	}
}
	
void GlIndexBuffer::DeleteBuffer()
{
	if(iboId!=0)
	{
		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
		glDeleteBuffersARB(1, &iboId);
		
		iboId  = 0;
	}
}
	

void	GlIndexBuffer::Lock()
{
		if (locked) 
		return;

	

	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, iboId);
	
	

	indexBuffer = (unsigned char*)(glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_READ_WRITE_ARB));

	if(!indexBuffer)
	{
		//FATAL("Unable to map GL VBO index buffer");
	}

	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);

	locked = true;
}
void	GlIndexBuffer::Unlock()
{
	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, iboId);
	
	if (!locked) 
		return;

	if(glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB)==GL_FALSE)
	{
		
	}
		
	indexBuffer = 0;

	locked = false;
}

unsigned GlIndexBuffer::VboCount()
{
	GLint size;
	glGetBufferParameterivARB(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE_ARB, &size);
	return	(unsigned) size;
}

GlIndexBuffer::~GlIndexBuffer()
{
	Clear();
}
}
